﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Collections.Specialized;
using System.Threading.Tasks;
using Windows.Data.Html;
using Windows.Storage;
using Sharepoint.Entities;
using SharePoint.Entities;
using TopGroup.MySharePoint.DataModel;
using System.ServiceModel;
using TopGroup.MySharePoint.ServiceUserGroup;
using System.Xml.Linq;
using TopGroup.MySharePoint.UserProfile;
using System.IO;
using Windows.Networking.BackgroundTransfer;
using TopGroup.MySharePoint.Common;
using Windows.Storage.Streams;
using System.Xml.Serialization;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net;
using System.Security.Principal;

// El modelo de datos definido por este archivo sirve como ejemplo representativo de un modelo
// fuertemente tipado que admite notificación cuando se agregan, quitan o modifican miembros. Los nombres
// de propiedad elegidos coinciden con enlaces de datos en las plantillas de elemento estándar.
//
// Las aplicaciones pueden usar este modelo como punto de inicio y ampliarlo o descartarlo completamente
// y reemplazarlo por algo adecuado a sus necesidades.

namespace TopGroup.MySharePoint.Data
{
    /// <summary>
    /// Clase base para <see cref="SampleDataItem"/> y <see cref="SampleDataGroup"/> que
    /// define propiedades comunes a ambos.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class SampleDataCommon : BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public SampleDataCommon(String uniqueId, String title, String phonenumber, String imagePath, String cellphone, String Manager, String Department, String Birthay, String HireDate, String JobTitle, String LocalitationOffice, String Titulo, String Workemail)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            this._phonenumber = phonenumber;
            this._imagePath = imagePath;
            this._cellphone = cellphone;
            this._Manager = Manager;
            this._Department = Department;
            this._Birthay = Birthay;
            this._HireDate = HireDate;
            this._JobTitle = JobTitle;
            this._LocalitationOffice = LocalitationOffice;
            this._Titulo = Titulo;
            this._WorkEmail = Workemail;

        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }
        private string _Titulo = string.Empty;
        public string Titulo
        {
            get { return this._Titulo; }
            set { this.SetProperty(ref this._Titulo, value); }
        }
        private string _WorkEmail = string.Empty;
        public string WorkEmail
        {
            get { return this._WorkEmail; }
            set { this.SetProperty(ref this._WorkEmail, value); }
        }

        private string _LocalitationOffice = string.Empty;
        public string LocalitationOffice
        {
            get { return this._LocalitationOffice; }
            set { this.SetProperty(ref this._LocalitationOffice, value); }
        }

        private string _JobTitle = string.Empty;
        public string JobTitle
        {
            get { return this._JobTitle; }
            set { this.SetProperty(ref this._JobTitle, value); }
        }

        private string _HireDate = string.Empty;
        public string HireDate
        {
            get { return this._HireDate; }
            set { this.SetProperty(ref this._HireDate, value); }
        }

        private string _Birthay = string.Empty;
        public string Birthay
        {
            get { return this._Birthay; }
            set { this.SetProperty(ref this._Birthay, value); }
        }

        private string _Department = string.Empty;
        public string Department
        {
            get { return this._Department; }
            set { this.SetProperty(ref this._Department, value); }
        }

        private string _Manager = string.Empty;
        public string Manager
        {
            get { return this._Manager; }
            set { this.SetProperty(ref this._Manager, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }


        private string _cellphone = string.Empty;
        public string cellphone
        {
            get { return this._cellphone; }
            set { this.SetProperty(ref this._cellphone, value); }
        }
        private string _phonenumber = string.Empty;
        public string phonenumber
        {
            get { return this._phonenumber; }
            set { this.SetProperty(ref this._phonenumber, value); }
        }

        private ImageSource _image = null;
        private String _imagePath = null;
        public ImageSource Image
        {
            get
            {
                if (this._image == null && this._imagePath != null)
                {
                    this._image = new BitmapImage(new Uri(SampleDataCommon._baseUri, this._imagePath));
                }
                return this._image;
            }

            set
            {
                this._imagePath = null;
                this.SetProperty(ref this._image, value);
            }
        }

        public void SetImage(String path)
        {
            this._image = null;
            this._imagePath = path;
            this.OnPropertyChanged("Image");
        }

        public override string ToString()
        {
            return this.Title;
        }
    }

    /// <summary>
    /// Modelo de datos de elemento genérico.
    /// </summary>
    public class SampleDataItem : SampleDataCommon
    {
        public SampleDataItem(String uniqueId, String title, String phonenumber, String imagePath, String cellphone, String Manager, String Department, String Birthay, String HireDate, String JobTitle, String LocalitationOffice, String Titulo, String Workemail, String content, SampleDataGroup group)
            : base(uniqueId, title, phonenumber, imagePath, cellphone, Manager, Department, Birthay, HireDate, JobTitle, LocalitationOffice, Titulo, Workemail)
        {
            this._content = content;
            this._group = group;
        }

        private string _content = string.Empty;
        public string Content
        {
            get { return this._content; }
            set { this.SetProperty(ref this._content, value); }
        }

        private SampleDataGroup _group;
        public SampleDataGroup Group
        {
            get { return this._group; }
            set { this.SetProperty(ref this._group, value); }
        }
    }

    /// <summary>
    /// Modelo de datos de grupo genérico.
    /// </summary>
    public class SampleDataGroup : SampleDataCommon
    {
        public SampleDataGroup(String uniqueId, String title, String phonenumber, String imagePath, String cellphone, String Manager, String Department, String Birthay, String HireDate, String JobTitle, String LocalitationOffice, String Titulo, String Workemail)
            : base(uniqueId, title, phonenumber, imagePath, cellphone, Manager, Department, Birthay, HireDate, JobTitle, LocalitationOffice, Titulo, Workemail)
        {
            Items.CollectionChanged += ItemsCollectionChanged;
        }

        public bool IsDocumentGroup
        {
            get;
            set;
        }

        private void ItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            // Proporciona un subconjunto de la colección completa de elementos al que enlazar desde un elemento GroupedItemsPage
            // por dos motivos: GridView no virtualiza colecciones de elementos grandes y
            // mejora la experiencia del usuario cuando examina grupos con números grandes de
            // elementos.
            //
            // Se muestra un máximo de 12 elementos porque da lugar a columnas de cuadrícula rellenas
            // ya se muestren 1, 2, 3, 4 o 6 filas
            int count = Convert.ToInt32(ApplicationData.Current.RoamingSettings.Values["contacts"].ToString());
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (e.NewStartingIndex < count)
                    {
                        TopItems.Insert(e.NewStartingIndex, Items[e.NewStartingIndex]);
                        if (TopItems.Count > count)
                        {
                            TopItems.RemoveAt(count);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Move:
                    if (e.OldStartingIndex < count && e.NewStartingIndex < count)
                    {
                        TopItems.Move(e.OldStartingIndex, e.NewStartingIndex);
                    }
                    else if (e.OldStartingIndex < count)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        TopItems.Add(Items[count]);
                    }
                    else if (e.NewStartingIndex < count)
                    {
                        TopItems.Insert(e.NewStartingIndex, Items[e.NewStartingIndex]);
                        TopItems.RemoveAt(count);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldStartingIndex < count)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        if (Items.Count >= count)
                        {
                            TopItems.Add(Items[count]);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    if (e.OldStartingIndex < count)
                    {
                        TopItems[e.OldStartingIndex] = Items[e.OldStartingIndex];
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    TopItems.Clear();
                    while (TopItems.Count < Items.Count && TopItems.Count < count)
                    {
                        TopItems.Add(Items[TopItems.Count]);
                    }
                    break;
            }
        }

        private ObservableCollection<SampleDataItem> _items = new ObservableCollection<SampleDataItem>();
        public ObservableCollection<SampleDataItem> Items
        {
            get { return this._items; }
        }

        private ObservableCollection<SampleDataItem> _topItem = new ObservableCollection<SampleDataItem>();
        public ObservableCollection<SampleDataItem> TopItems
        {
            get { return this._topItem; }
        }
    }

    /// <summary>
    /// Crea una colección de grupos y elementos con contenido codificado de forma rígida.
    /// 
    /// SampleDataSource se inicializa con datos de marcadores de posición en lugar de con datos de producción
    /// activos, por lo que se proporcionan datos de muestra tanto en el momento del diseño como en el de la ejecución.
    /// </summary>
    public sealed class SampleDataSource
    {
        private static SampleDataSource _sampleDataSource = new SampleDataSource();
        private Dictionary<string, List<SampleDataItem>> _results = new Dictionary<string, List<SampleDataItem>>();

        private static ObservableCollection<SampleDataGroup> allGroups = new ObservableCollection<SampleDataGroup>();
        public static ObservableCollection<SampleDataGroup> AllGroups
        {
            set { allGroups = value; }
            get { if (allGroups == null) allGroups = new ObservableCollection<SampleDataGroup>(); return allGroups; }
        }

        public static IEnumerable<SampleDataGroup> Reload()
        {
            SampleDataSource _sampleDataSource = new SampleDataSource();
            _sampleDataSource._results.Clear();
            AllGroups.Clear();
            return AllGroups;
        }
      

        public static IEnumerable<SampleDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");
            //return _sampleDataSource.AllGroups;
            return AllGroups;
        }

        public static SampleDataGroup GetGroup(string uniqueId)
        {
            // La búsqueda lineal sencilla es aceptable para conjuntos de datos reducidos
            var matches = AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static SampleDataItem GetItem(string uniqueId)
        {
            // La búsqueda lineal sencilla es aceptable para conjuntos de datos reducidos
            var matches = AllGroups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static async Task<List<TGUsers>> GetUserInfoAsync(TGParametters parameters)
        {
            TGUsers user = null;
            List<TGUsers> users = new List<TGUsers>();
            BasicHttpBinding binding = new BasicHttpBinding();
            try
            { 
                binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
                binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
                EndpointAddress address = new EndpointAddress(parameters.Url + "/_vti_bin/usergroup.asmx");
                UserGroupSoapClient userGroup = new UserGroupSoapClient(binding, address);
                userGroup.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation;
                userGroup.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(parameters.Login, parameters.Password, parameters.Dominio);
                GetAllUserCollectionFromWebResponse allUsers = await userGroup.GetAllUserCollectionFromWebAsync();
                //XNode xNode = ((System.Xml.Linq.XNode)(allUsers.Body.GetAllUserCollectionFromWebResult));
                XElement collectionResult = allUsers.Body.GetAllUserCollectionFromWebResult;
                int count = Convert.ToInt32(ApplicationData.Current.RoamingSettings.Values["contacts"].ToString());
                var result = (from root in collectionResult.Elements().Elements()
                             let loginName = (string)root.Attribute("LoginName")
                             where loginName != "SHAREPOINT\\system" &&
                                 loginName != "NT AUTHORITY\\LOCAL SERVICE" &&
                                 loginName != "NT AUTHORITY\\SERVICIO LOCAL" &&
                                 loginName != "NT AUTHORITY\\usuarios autentificados"
                             select root).Take(count);

                foreach (var temp in result)
                {
                    var loginName = (string)temp.Attribute("LoginName");
                    try
                    {
                        var userInfo = await GetUserInfoDetailsAsync(loginName, parameters);
                        if (!string.IsNullOrEmpty(userInfo.Title))
                        {
                            user = new TGUsers();
                            user.Title = userInfo.Title;
                            user.Image = userInfo.Image;
                            user.Id = loginName;
                            user.Phonenumber = userInfo.Phonenumber;
                            user.Manager = userInfo.Manager;
                            user.Cellphone = userInfo.Cellphone;
                            user.Birthay = userInfo.Birthay;
                            user.Department = userInfo.Department;
                            user.HireDate = userInfo.HireDate;
                            user.JobTitle = userInfo.JobTitle;
                            user.Localitationoffice = userInfo.Localitationoffice;
                            user.Titulo = userInfo.Titulo;
                            user.Workemail = userInfo.Workemail;
                            users.Add(user);
                        }
                    }
                    catch(Exception ex) 
                    {
                        throw;
                    }   
                }
                return users;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public static async Task<TGUsers> GetUserInfoDetailsAsync(string loginName, TGParametters parameters)
        {
            TGUsers userInfo = null;
            if (loginName != "SHAREPOINT\\system" && loginName != "NT AUTHORITY\\LOCAL SERVICE")
            {
                userInfo = new TGUsers();
                BasicHttpBinding binding = new BasicHttpBinding();
                userInfo.Image = "ms-appx:///Assets/usuario.jpg";
                try
                {
                    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
                    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
                    EndpointAddress address = new EndpointAddress(parameters.Url + "/_vti_bin/userprofileservice.asmx");
                    UserProfileServiceSoapClient userprofile = new UserProfileServiceSoapClient(binding, address);
                    userprofile.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation;
                    userprofile.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(parameters.Login, parameters.Password, parameters.Dominio);
                    GetUserProfileByNameResponse data = await userprofile.GetUserProfileByNameAsync(loginName);
                     string pictureUrl = GetPropertyData(data, "PictureURL");
                    if (!string.IsNullOrEmpty(pictureUrl))
                    {
                        await GetImageUser2(pictureUrl, loginName.Split('\\')[1], parameters);
                        userInfo.Image = "ms-appdata:///local/" + loginName.Split('\\')[1] + ".png";
                    }
                    userInfo.Title = GetPropertyData(data, "FirstName") + " " + GetPropertyData(data, "LastName");
                    if (string.IsNullOrWhiteSpace(userInfo.Title))
                    {
                        userInfo.Title = GetPropertyData(data, "AccountName");
                    }
                    userInfo.Phonenumber = GetPropertyData(data, "WorkPhone");
                    userInfo.Cellphone = GetPropertyData(data, "CellPhone");
                    userInfo.Manager = GetPropertyData(data, "Manager");
                    userInfo.Department = GetPropertyData(data, "Department");
                    userInfo.Birthay = GetPropertyData(data, "SPS-Birthday");
                    userInfo.HireDate = GetPropertyData(data, "SPS-HireDate");
                    userInfo.JobTitle = GetPropertyData(data, "SPS-JobTitle");
                    userInfo.Localitationoffice = GetPropertyData(data, "SPS-Location");
                    userInfo.Titulo = GetPropertyData(data, "Title");
                    userInfo.Workemail = GetPropertyData(data, "WorkEmail");

                }
                catch
                {
                    
                }
            }
            return userInfo;
        }

        private static string GetPropertyData(GetUserProfileByNameResponse data, string columnName)
        {
            try
            {
                //Delimit properties with a semi-colon or comma.
                return string.Join("; ",
                    (from v in
                         ((PropertyData)data.Body.GetUserProfileByNameResult.Where(x => x.Name == columnName).Single()).Values
                     select v.Value.ToString()).ToArray());
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }


        public static AuthenticationHeaderValue CreateBasicHeader(string username, string password)
        {
            byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(username + ":" + password);
            return new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
        }

        public static async Task<bool> ContainsFileAsync(StorageFolder folder, string filename)
        {
            var files = await folder.GetFilesAsync();
            return files.Any(l => l.Name == filename);
        }

        public static async Task GetImageUser2(string thumbnail, string title, TGParametters parameters)
        {
            thumbnail = thumbnail.Replace("MThumb", "LThumb");
            BackgroundDownloader downloader = new BackgroundDownloader();
            Uri source = new Uri(thumbnail);
            StorageFile destinationFile = null;
            DownloadOperation download = null;
            ResponseInformation response = null;
            var path = Windows.Storage.ApplicationData.Current.LocalFolder;
            parameters.AppPath = path.Path + "\\";
            try
            {
                bool exist = await ContainsFileAsync(path,title);
                if (!exist)
                {
                    destinationFile = await path.CreateFileAsync(title + ".png", CreationCollisionOption.ReplaceExisting);
                    using (IRandomAccessStream random = await destinationFile.OpenAsync(FileAccessMode.Read))
                    {
                        using (Stream stream = random.AsStreamForRead())
                        {
                            downloader.ServerCredential = new Windows.Security.Credentials.PasswordCredential();
                            downloader.ServerCredential.Password = parameters.Password;
                            downloader.ServerCredential.UserName = parameters.Dominio + @"\" + parameters.Login;
                            download = downloader.CreateDownload(source, destinationFile);
                            await download.StartAsync();
                            response = download.GetResponseInformation();
                            stream.Flush();
                        }
                    }
                }
            }
            catch (FileNotFoundException ex)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public static async Task GetUserInfoAsync()
        {
            string birthday = string.Empty;
            string hireDate = string.Empty;
            Sharepoint.Entities.TGParametters parameters = new Sharepoint.Entities.TGParametters();
            try
            {
                parameters.Login = ApplicationData.Current.RoamingSettings.Values["login"].ToString();
                parameters.Password = ApplicationData.Current.RoamingSettings.Values["password"].ToString();
                parameters.Dominio = ApplicationData.Current.RoamingSettings.Values["dominio"].ToString();
                parameters.Url = ApplicationData.Current.RoamingSettings.Values["url"].ToString();
                List<TGUsers> items = await GetUserInfoAsync(parameters);
                String ITEM_CONTENT = String.Format("Item Content: {0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}",
                           "");
                var A = new SampleDataGroup("Group-A",
                        "Contacts",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Title: A",
                        "Group Subtitle: A",
                        "Assets/usuario.jpg",
                        "Group Description: L   orem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante",
                        "3198766473");
                foreach (TGUsers item in items)
                {
                    if (!string.IsNullOrEmpty(item.Birthay))
                        birthday = Convert.ToDateTime(item.Birthay).ToString("dd MMMM");
                    if (!string.IsNullOrEmpty(item.HireDate))
                        hireDate = Convert.ToDateTime(item.HireDate).ToString("dd MMM yyyy");
                    A.Items.Add(new SampleDataItem(item.Id, item.Title, item.Phonenumber, item.Image, item.Cellphone, item.Manager, item.Department, birthday, hireDate, item.JobTitle, item.Localitationoffice, item.Titulo, item.Workemail, ITEM_CONTENT, A));
                }
                AllGroups.Add(A);
            }
            catch (Exception ex)
            {
                var dlg = new Windows.UI.Popups.MessageDialog("\nPlease go to settings and check the credentials of the site");
                dlg.ShowAsync();
            }
        }
        public SampleDataSource()
        {

        }

        private sealed class Filter : TopGroup.MySharePoint.Common.BindableBase
        {
            private String _name;
            private int _count;
            private bool _active;

            public Filter(String name, int count, bool active = false)
            {
                this.Name = name;
                this.Count = count;
                this.Active = active;
            }

            public override String ToString()
            {
                return Description;
            }

            public String Name
            {
                get { return _name; }
                set { if (this.SetProperty(ref _name, value)) this.OnPropertyChanged("Description"); }
            }

            public int Count
            {
                get { return _count; }
                set { if (this.SetProperty(ref _count, value)) this.OnPropertyChanged("Description"); }
            }

            public bool Active
            {
                get { return _active; }
                set { this.SetProperty(ref _active, value); }
            }

            public String Description
            {
                get { return String.Format("{0} ({1})", _name, _count); }
            }
        }
    }
}
